﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Microsoft.SharePoint;
using Microsoft.SharePoint.Publishing;
using Microsoft.SharePoint.WebPartPages;
using Microsoft.SharePoint.Security;

using System.Xml;
using System.Security.Cryptography;
using System.IO;
using System.Web.UI.WebControls.WebParts;

using SPBusiness.ExtensionMethods;

namespace SPBusiness
{
   public sealed class File
   {
      /// <summary>
      /// File class has only Static Methods, no constructor needed.
      /// </summary>
      private File() { }

      #region "Best Methods"

      public static void ApproveElevated(string pSiteUrl, string pWebUrl, string pFileUrl)
      {
         try
         {
            //SPSecurity.RunWithElevatedPrivileges(delegate()
    // {
        using (SPSite vSPSite = new SPSite(pSiteUrl))
        {
           using (SPWeb vSPWeb = vSPSite.OpenWeb(pWebUrl))
           {

              CheckInElevated(pSiteUrl, pWebUrl, pFileUrl, SPCheckinType.MajorCheckIn);
              PublishElevated(pSiteUrl, pWebUrl, pFileUrl);

              SPFile vSPFile = vSPWeb.GetFile(pFileUrl);

              if (vSPFile.DocumentLibrary.EnableModeration)
              {

                 Int32 pErrorCount = 0;

                 while (vSPFile.Item.ModerationInformation.Status == SPModerationStatusType.Pending)
                 {
                    try
                    {
                       vSPFile.Approve(string.Empty);
                       break;
                    }
                    catch (Exception)
                    {
                       pErrorCount += 1;

                       if (pErrorCount != 3)
                       {
                          System.Threading.Thread.Sleep(100);
                       }
                       else
                       {
                          throw;
                       }
                    }
                 }
              }
           }
        }
     //});

         }
         catch (Exception ex)
         {
            Logging.LogMessase(typeof(File).Namespace, typeof(File).Name, "ApproveElevated", ex);
            throw;
         }
      }

      public static void PublishElevated(string pSiteUrl, string pWebUrl, string pFileUrl)
      {
         try
         {
            //SPSecurity.RunWithElevatedPrivileges(delegate()
     //{
        using (SPSite vSPSite = new SPSite(pSiteUrl))
        {
           using (SPWeb vSPWeb = vSPSite.OpenWeb(pWebUrl))
           {

              CheckInElevated(pSiteUrl, pWebUrl, pFileUrl, SPCheckinType.MajorCheckIn);

              SPFile vSPFile = vSPWeb.GetFile(pFileUrl);

              if (vSPFile.DocumentLibrary.EnableMinorVersions)
              {

                 Int32 pErrorCount = 0;

                 while (vSPFile.Level == SPFileLevel.Draft)
                 {
                    try
                    {
                       vSPFile.Publish(string.Empty);
                       break;
                    }
                    catch (Exception)
                    {
                       pErrorCount += 1;

                       if (pErrorCount != 3)
                       {
                          System.Threading.Thread.Sleep(100);
                       }
                       else
                       {
                          throw;
                       }
                    }
                 }

              }
           }
        }
     //});

         }
         catch (Exception ex)
         {
            Logging.LogMessase(typeof(File).Namespace, typeof(File).Name, "PublishElevated", ex);
            throw;
         }
      }

      public static void CheckInElevated(string pSiteUrl, string pWebUrl, string pFileUrl, SPCheckinType vSPCheckinType)
      {
         try
         {
            //SPSecurity.RunWithElevatedPrivileges(delegate()
    // {
        using (SPSite vSPSite = new SPSite(pSiteUrl))
        {
           using (SPWeb vSPWeb = vSPSite.OpenWeb(pWebUrl))
           {

              SPFile vSPFile = vSPWeb.GetFile(pFileUrl);
              if (vSPFile.CheckOutType != SPFile.SPCheckOutType.None)
              {
                 if (vSPFile.CheckedOutByUser.ID != vSPFile.Web.CurrentUser.ID)
                 {

                    SPDocumentLibrary vSPDocumentLibrary = vSPFile.DocumentLibrary;

                    SPCheckedOutFile vSPCheckedOutFile = vSPDocumentLibrary.CheckedOutFiles.OfType<SPCheckedOutFile>().Where(x => x.ListItemId == vSPFile.Item.ID).FirstOrDefault();

                    SPListItem vSPListItem = null;
                    if (vSPCheckedOutFile != null)
                    {
                       vSPCheckedOutFile.TakeOverCheckOut();
                       vSPListItem = vSPDocumentLibrary.GetItemById(vSPCheckedOutFile.ListItemId);
                       vSPListItem.File.CheckIn(string.Empty, SPCheckinType.MajorCheckIn);
                    }
                    else
                    {
                       vSPListItem = ListItem.InstanciateByCheckOutUser(vSPFile.Item);
                       SPWeb vSPWebCheckOutUser = vSPListItem.Web;
                       SPSite vSPSiteCheckOutUser = vSPWebCheckOutUser.Site;

                       vSPListItem.File.CheckIn(string.Empty, vSPCheckinType);

                       vSPWebCheckOutUser.Close();
                       vSPWebCheckOutUser.Dispose();
                       vSPWebCheckOutUser = null;

                       vSPSiteCheckOutUser.Close();
                       vSPSiteCheckOutUser.Dispose();
                       vSPSiteCheckOutUser = null;

                    }

                 }
                 else
                 {
                    vSPFile.CheckIn(string.Empty, SPCheckinType.MajorCheckIn);
                 }
              }
           }
        }
     //});
         }
         catch (Exception ex)
         {
            Logging.LogMessase(typeof(File).Namespace, typeof(File).Name, "CheckInElevated", ex);
            throw;
         }
      }

      #endregion


      public static void Approve(SPFile pSPFile)
      {
         try
         {
            CheckIn(pSPFile, SPCheckinType.MajorCheckIn);
            Publish(pSPFile);


            if (pSPFile.DocumentLibrary.EnableModeration)
            {

               Int32 pErrorCount = 0;

               while (pSPFile.Item.ModerationInformation.Status == SPModerationStatusType.Pending)
               {
                  try
                  {
                     pSPFile.Approve(string.Empty);
                     break;
                  }
                  catch (Exception)
                  {
                     pErrorCount += 1;

                     if (pErrorCount != 3)
                     {
                        System.Threading.Thread.Sleep(100);
                     }
                     else
                     {
                        throw;
                     }
                  }
               }
            }

         }
         catch (Exception ex)
         {
            Logging.LogMessase(typeof(File).Namespace, typeof(File).Name, "Approve", ex);
            throw;
         }
      }

      public static void Publish(SPFile pSPFile)
      {
         try
         {

            CheckIn(pSPFile, SPCheckinType.MajorCheckIn);

            if (pSPFile.DocumentLibrary.EnableMinorVersions)
            {

               Int32 pErrorCount = 0;

               while (pSPFile.Level == SPFileLevel.Draft)
               {
                  try
                  {
                     pSPFile.Publish(string.Empty);
                     break;
                  }
                  catch (Exception)
                  {
                     pErrorCount += 1;

                     if (pErrorCount != 3)
                     {
                        System.Threading.Thread.Sleep(100);
                     }
                     else
                     {
                        throw;
                     }
                  }
               }

            }

         }
         catch (Exception ex)
         {
            Logging.LogMessase(typeof(File).Namespace, typeof(File).Name, "Publish", ex);
            throw;
         }
      }

      public static void CheckIn(SPFile pSPFile, SPCheckinType vSPCheckinType)
      {
         try
         {
            if (pSPFile.CheckOutType != SPFile.SPCheckOutType.None)
            {
               if (pSPFile.CheckedOutByUser.ID != pSPFile.Web.CurrentUser.ID)
               {

                  //Método 1 para alcançar o Checkin

                  SPDocumentLibrary vSPDocumentLibrary = pSPFile.DocumentLibrary;

                  SPCheckedOutFile vSPCheckedOutFile = vSPDocumentLibrary.CheckedOutFiles.OfType<SPCheckedOutFile>().Where(x => x.ListItemId == pSPFile.Item.ID).FirstOrDefault();

                  if (vSPCheckedOutFile != null)
                  {
                     vSPCheckedOutFile.TakeOverCheckOut();
                     SPListItem vSPListItem = vSPDocumentLibrary.GetItemById(vSPCheckedOutFile.ListItemId);
                     vSPListItem.File.CheckIn(string.Empty, vSPCheckinType);
                  }
                  else
                  {

                     //Método 2 para alcançar o Checkin
                     SPListItem vSPListItem = ListItem.InstanciateByCheckOutUser(pSPFile.Item);
                     vSPListItem.File.CheckIn(string.Empty);

                     SPWeb vSPWebElevated = vSPListItem.Web;
                     SPSite vSPSiteElevated = vSPListItem.Web.Site;

                     vSPWebElevated.Close();
                     vSPWebElevated.Dispose();
                     vSPWebElevated = null;

                     vSPSiteElevated.Close();
                     vSPSiteElevated.Dispose();
                     vSPSiteElevated = null;
                  }
               }
               else
               {
                  pSPFile.CheckIn(string.Empty);
               }
            }
         }
         catch (Exception ex)
         {
            Logging.LogMessase(typeof(File).Namespace, typeof(File).Name, "CheckIn", ex);
            throw;
         }
      }

      public static void CheckOut(SPFile pSPFile)
      {
         try
         {
            if (pSPFile.CheckOutType != SPFile.SPCheckOutType.None)
            {
               if (pSPFile.CheckedOutByUser.ID != pSPFile.Web.CurrentUser.ID)
               {
                  CheckIn(pSPFile, SPCheckinType.MinorCheckIn);
                  SPFile vSPFile = pSPFile.Web.GetFile(pSPFile.ServerRelativeUrl);
                  pSPFile.CheckOut();
               }
            }
            else
            {
               pSPFile.CheckOut();
            }
         }
         catch (Exception ex)
         {
            Logging.LogMessase(typeof(File).Namespace, typeof(File).Name, "CheckOut", ex);
            throw;
         }
      }

      public static void Publish(SPFile pSPFile, SPCheckinType vSPCheckinType)
      {
         try
         {

            CheckIn(pSPFile, vSPCheckinType);

            if (pSPFile.DocumentLibrary.EnableMinorVersions)
            {

               Int32 pErrorCount = 0;

               while (pSPFile.Level == SPFileLevel.Draft)
               {
                  try
                  {
                     pSPFile.Publish(string.Empty);
                     break;
                  }
                  catch (Exception)
                  {
                     pErrorCount += 1;

                     if (pErrorCount != 3)
                     {
                        System.Threading.Thread.Sleep(100);
                     }
                     else
                     {
                        throw;
                     }
                  }
               }

            }

         }
         catch (Exception ex)
         {
            Logging.LogMessase(typeof(File).Namespace, typeof(File).Name, "Publish", ex);
            throw;
         }
      }

      public static SPFile InstanciateByCheckOutUser(SPFile pSPFile)
      {
         try
         {
            SPUserToken vSPUserToken = null;

            if (pSPFile.CheckedOutByUser != null)
            {
               vSPUserToken = pSPFile.CheckedOutByUser.UserToken;
            }

            if (vSPUserToken != null)
            {
               using (SPSite vSPSite = new SPSite(pSPFile.Web.Site.Url, vSPUserToken))
               {
                  using (SPWeb vSPWeb = vSPSite.OpenWeb(pSPFile.Web.ID))
                  {

                     SPList vSPList = vSPWeb.Lists[pSPFile.Item.ParentList.ID];
                     return vSPList.GetItemById(pSPFile.Item.ID).File;
                  }
               }
            }
            return null;
         }
         catch (Exception ex)
         {
            Logging.LogMessase(typeof(ListItem).Namespace, typeof(ListItem).Name, "InstanciateByCheckOutUser", ex);
            throw;
         }


      }

      public static void AddWebPart(string pSiteUrl, string pWebUrl, string pFileUrl, System.Web.UI.WebControls.WebParts.WebPart pWebPart, string pWebPartZondeID, Int32 pZoneIndex, System.Web.UI.WebControls.WebParts.PersonalizationScope pPersonalizationScope)
      {
         try
         {
            using (SPSite vSPSite = new SPSite(pSiteUrl))
            {
               using (SPWeb vSPWeb = vSPSite.OpenWeb(pWebUrl))
               {

                  SPFile vSPFile = vSPWeb.TryGetFileByUrl(vSPWeb.ServerRelativeUrl + "/" + pFileUrl);

                  if (vSPFile != null)
                  {
                     using (SPLimitedWebPartManager vSPLimitedWebPartManager = vSPFile.GetLimitedWebPartManager(pPersonalizationScope))
                     {
                        try
                        {
                           CheckOut(vSPLimitedWebPartManager.Web.GetFile(vSPFile.UniqueId));

                           vSPLimitedWebPartManager.AddWebPart(pWebPart, pWebPartZondeID, pZoneIndex);
                           vSPLimitedWebPartManager.SaveChanges(pWebPart);

                           vSPFile.Update();

                           Approve(vSPLimitedWebPartManager.Web.GetFile(vSPFile.UniqueId));
                        }
                        finally
                        {
                           vSPLimitedWebPartManager.Web.Dispose();
                        }
                     }


                  }
               }
            }

         }
         catch (Exception ex)
         {
            Logging.LogMessase(typeof(File).Namespace, typeof(File).Name, "AddWebPart", ex);
            throw;
         }
      }

      public static void RemoveWebPart(string pSiteUrl, string pWebUrl, string pFileUrl, System.Web.UI.WebControls.WebParts.WebPart pWebPart, System.Web.UI.WebControls.WebParts.PersonalizationScope pPersonalizationScope)
      {
         try
         {
            using (SPSite vSPSite = new SPSite(pSiteUrl))
            {
               using (SPWeb vSPWeb = vSPSite.OpenWeb(pWebUrl))
               {

                  SPFile vSPFile = vSPWeb.TryGetFileByUrl(vSPWeb.ServerRelativeUrl + "/" + pFileUrl);

                  if (vSPFile != null)
                  {
                     using (SPLimitedWebPartManager vSPLimitedWebPartManager = vSPFile.GetLimitedWebPartManager(pPersonalizationScope))
                     {
                        try
                        {


                           var vWebParts = from System.Web.UI.WebControls.WebParts.WebPart webPart in vSPLimitedWebPartManager.WebParts
                                           where webPart.Title == pWebPart.Title
                                           select webPart;


                           if (vWebParts.Count() > 0)
                           {
                              CheckOut(vSPLimitedWebPartManager.Web.GetFile(vSPFile.UniqueId));

                              System.Web.UI.WebControls.WebParts.WebPart vWebPart = vWebParts.FirstOrDefault();

                              vSPLimitedWebPartManager.DeleteWebPart(vWebPart);

                              vSPFile.Update();

                              Approve(vSPLimitedWebPartManager.Web.GetFile(vSPFile.UniqueId));
                           }
                        }
                        finally
                        {
                           vSPLimitedWebPartManager.Web.Dispose();
                        }
                     }

                  }
               }
            }

         }
         catch (Exception ex)
         {
            Logging.LogMessase(typeof(File).Namespace, typeof(File).Name, "RemoveWebPart", ex);
            throw;
         }
      }

      public static void SetPageLayout(string pSiteUrl, string pWebUrl, string pFileUrl, string pPageLayoutName)
      {
         try
         {
            //SPSecurity.RunWithElevatedPrivileges(delegate()
         // {

             using (SPSite vSPSite = new SPSite(pSiteUrl))
             {
                using (SPWeb vSPWeb = vSPSite.OpenWeb(pWebUrl))
                {

                   SPFile vSPFile = vSPWeb.GetFile(pFileUrl);

                   if (vSPFile != null)
                   {

                      File.CheckOut(vSPFile);

                      PublishingWeb vPublishingWeb = PublishingWeb.GetPublishingWeb(vSPWeb);

                      PageLayout[] vPageLayouts = vPublishingWeb.GetAvailablePageLayouts();

                      PageLayout vPageLayout = vPageLayouts.OfType<PageLayout>().Where(x => x.Name == pPageLayoutName).FirstOrDefault();

                      if (vPageLayout != null)
                      {
                         SPListItem vSPListItem = vSPFile.ListItemAllFields;
                         PublishingPage vPublishingPage = PublishingPage.GetPublishingPage(vSPListItem);
                         vPublishingPage.Layout = vPageLayout;
                         vPublishingPage.ListItem.Update();
                         vPublishingPage.Update();

                      }

                      File.Approve(vSPFile);

                   }

                }
             }
          //});

         }
         catch (Exception ex)
         {
            Logging.LogMessase(typeof(File).Namespace, typeof(File).Name, "SetPageLayout", ex);
            throw;
         }

      }

      public static void CleanupPublishingInfo(string pSiteUrl, string pWebUrl, string pFileUrl)
      {
         try
         {
            //SPSecurity.RunWithElevatedPrivileges(delegate()
//{

   using (SPSite vSPSite = new SPSite(pSiteUrl))
   {
      using (SPWeb vSPWeb = vSPSite.OpenWeb(pWebUrl))
      {


         SPFile vSPFile = vSPWeb.GetFile(pFileUrl);

         if (vSPFile != null)
         {
            File.CheckOut(vSPFile);

            SPListItem vSPListItem = vSPFile.ListItemAllFields;

            if (vSPListItem != null)
            {
               PublishingPage vPublishingPage = PublishingPage.GetPublishingPage(vSPListItem);
               vPublishingPage.Contact = null;
               vSPListItem.Update();
               vPublishingPage.Update();
            }

            File.Approve(vSPFile);

         }

      }
   }
//});

         }
         catch (Exception ex)
         {
            Logging.LogMessase(typeof(File).Namespace, typeof(File).Name, "CleanupPublishingInfo", ex);
            throw;
         }

      }

      public static void Delete(string pSiteUrl, string pWebUrl, string pFileUrl)
      {
         try
         {
            //SPSecurity.RunWithElevatedPrivileges(delegate()
            //{

               using (SPSite vSPSite = new SPSite(pSiteUrl))
               {
                  using (SPWeb vSPWeb = vSPSite.OpenWeb(pWebUrl))
                  {


                     SPFile vSPFile = vSPWeb.TryGetFileByUrl(pFileUrl);

                     if (vSPFile != null)
                     {
                        vSPFile.Delete();

                     }

                  }
               }
            //});

         }
         catch (Exception ex)
         {
            Logging.LogMessase(typeof(File).Namespace, typeof(File).Name, "Delete", ex);
            throw;
         }

      }

      public static void RemoveDuplicateWebParts(SPFile pSPFile)
      {
         try
         {

            CheckOut(pSPFile);
            SPFile vSPFile = pSPFile.Web.GetFile(pSPFile.ServerRelativeUrl);

            using (SPLimitedWebPartManager vSPLimitedWebPartManager = vSPFile.GetLimitedWebPartManager(PersonalizationScope.Shared))
            {

               List<string> webParts = new List<string>();

               if (vSPLimitedWebPartManager.WebParts.Count > 1)
               {
                  for (int index = (vSPLimitedWebPartManager.WebParts.Count - 1); index >= 0; index--)
                  {
                     var vStringBuilder = new StringBuilder();

                     XmlWriterSettings vXmlWriterSettings = new XmlWriterSettings();
                     vXmlWriterSettings.OmitXmlDeclaration = true;
                     XmlWriter vXmlWriter = XmlWriter.Create(vStringBuilder, vXmlWriterSettings);

                     System.Web.UI.WebControls.WebParts.WebPart vWebPart = vSPLimitedWebPartManager.WebParts[index];

                     vSPLimitedWebPartManager.ExportWebPart(vWebPart, vXmlWriter);
                     vXmlWriter.Flush();

                     using (MD5 md5Hash = MD5.Create())
                     {
                        string vHash = md5Hash.GetMd5Hash(vStringBuilder.ToString());
                        if (webParts.Contains(vHash))
                        {
                           vSPLimitedWebPartManager.DeleteWebPart(vWebPart);
                        }
                        else
                        {
                           webParts.Add(vHash);
                        }
                     }
                  }


               }
            }

            Approve(vSPFile);

         }
         catch (Exception ex)
         {
            Logging.LogMessase(typeof(File).Namespace, typeof(File).Name, "RemoveDuplicateWebParts", ex);
            throw;
         }

      }


   }
}
